#include "composition.h"


#define MAX_JOIN 2
#define MAX_DIST 1000
#define UNDER_GROUND 16


vector<ComPosition> gPositions;                             
    //collects all input computer locations

vector<Connection> gConnect;                                 
    //collects all optimal computer connections

vector<int> gCompNum;                                        
   //collects no. of computers in each specified network

ComPosition :: ComPosition():mX(0),mY(0),mJoins(0){}

ComPosition :: ComPosition(int x,int y):mX(x),mY(y),mJoins(0){}

void ComPosition::valuePos(int x,int y)
 {mX = x;
  mY = y;
 }


  
float ComPosition::distance(ComPosition &Pos)
 {int xDiff,yDiff,total;
  double distancePos;
  xDiff = mX - Pos.mX;
  yDiff = mY - Pos.mY;
  total = xDiff*xDiff + yDiff*yDiff;
  distancePos = sqrt((double)total);
  return distancePos;
 }



ComPosition& ComPosition :: operator=(const ComPosition &Pos)
 {mX = Pos.mX;
  mY = Pos.mY;
  mJoins = Pos.mJoins;
  return *this;
 }


int operator==(ComPosition &Po1,ComPosition &Po2)
 {
  return (Po1.mX == Po2.mX) && (Po1.mY == Po2.mY);
 }



void getComPositions(ifstream &infile)
 {ComPosition Pos;
  int x,y;
  int num = 0;
  int term = 0;
  do
   { infile >> num;
     term = num;
     if(num!=0)
     gCompNum.push_back(num);
     while(num!=0)
     {infile >> x;
      infile >> y;
      num--;
      Pos.valuePos(x,y);
      gPositions.push_back(Pos);
     }
   }while(term);
 }



void displayConnection(void)
 {double total = 0.0; 
  for(int k = 0;k!=gCompNum.size();k++)
  {for(int i = 0;i!=(gCompNum[k]-1);i++)
   {cout << "The length joining " ;
    cout << "(" <<gConnect[i].Po1.getX() << ",";
    cout << gConnect[i].Po1.getY() << ")" << "and";
    cout << "(" <<gConnect[i].Po2.getX() << ",";
    cout << gConnect[i].Po2.getY() << ") is";
    cout << gConnect[i].mDistance << endl;
    total = total + gConnect[i].mDistance + UNDER_GROUND;
   }
  cout << "total cable required is : "<< total << endl;
  total = 0.0;
  }
 }  





void reduceFunction(int indexPositions)
{vector<ComPosition> Reduce;
 for(int m=0;m!=gPositions.size();m++)
     {if(m!=indexPositions)
       Reduce.push_back(gPositions[m]);
     }
    gPositions = Reduce;
}


 
void createConnection(ComPosition &aPosition,ComPosition &bPosition,double minDist)

{Connection Connect;
 Connect.Po1 = aPosition;
 Connect.Po2 = bPosition;
 Connect.mDistance = minDist;
 gConnect.push_back(Connect);

}



void minDistance(void)
{double minDist =MAX_DIST;
 int indexOrderPos,indexPositions;
 int i = 0,num=0;
   //ONLY 4 LOOPS AHEAD!!!! NOT ALL { } ARE LOOPS

 for(int k = 0;k!=gCompNum.size();k++)              
 {     
        //loop for all k computer networks input
 
   vector<ComPosition> orderPos;                    
        //collects connected ComPositions'

   orderPos.push_back(gPositions[k]);               
       //add first ComPosition in kth network 
  
   num = gCompNum[k];                               
       //num has no. of computers in kth network
   
   while(orderPos.size()!=gCompNum[k])
   {    
    for(i=0;i!=orderPos.size();i++)
     
     {
      if(orderPos[i].mJoins <MAX_JOIN)      
       {//NO MORE THAN TWO JOINS

        for(int j=k+1;(j!=num+k);j++)    
         {//k+1 to avoid comparing with first element with itself
          
            if(minDist > orderPos[i].distance(gPositions[j]))
             {
              minDist = orderPos[i].distance(gPositions[j]);
              indexOrderPos = i;
              indexPositions = j;
             } 
           
        
         }

       } 
     } 
     orderPos[indexOrderPos].mJoins++;
     gPositions[indexPositions].mJoins++;
    
     createConnection(orderPos[indexOrderPos],gPositions[indexPositions],minDist);
     orderPos.push_back(gPositions[indexPositions]);
     minDist = MAX_DIST;
     reduceFunction(indexPositions);
     num--;
   }
 }
}

 
